package javaproject;

import com.sun.j3d.utils.geometry.Cone;
import com.sun.j3d.utils.geometry.Sphere;
import java.util.Iterator;
import java.util.LinkedList;
import javax.media.j3d.*;
import javax.vecmath.Color3f;
import javax.vecmath.Vector3f;

public class Capsule extends MyPrimitive{
    public double vx,vy,vz;
    Capsule(double x, double y, double z, Appearance app)
    {
        super(x,y,z,app);

	float ballSize = 0.025f;
	float offsetX = 0.035f;
	float height = 0.015f;
	float outerR = 0.03f;
/*
	int edges = 8;
	int coneVertices = (edges+2)*2*2;   //內外兩片，左右再兩片
	int rectVertices = edges*4*2;	    //一片四點，左右再兩片
	int[] stripCounts = {edges+2, edges+2, edges+2, edges+2};
	int[] stripQuadCounts = {4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4};

	//Point3d[] coneCoords = new Point3d[coneVertices];
	//Point3d[] rectCoords = new Point3d[rectVertices];

	float offsetX = 0.02f;
	double offsetX2 = 0.035;
	double offsetX3 = 0.04;
	float outerR = 0.025f;
	double innerR = 0.01;

	Color3f capWhite = new Color3f(0.3f,0.5f,0.7f);

	coneCoords[0*(edges+2)] = new Point3d(-offsetX2,0,0);
	coneCoords[1*(edges+2)] = new Point3d(-offsetX3,0,0);
	coneCoords[2*(edges+2)] = new Point3d(offsetX2,0,0);
	coneCoords[3*(edges+2)] = new Point3d(offsetX3,0,0);

	for(int i = 0; i <= edges; i++)
	{
	    coneCoords[0*(edges+2)+i+1] =	    new Point3d(-offsetX1, outerR*Math.cos(2*Math.PI/edges*i), outerR*Math.sin(2*Math.PI/edges*i));
	    coneCoords[1*(edges+2)+(edges+1)-i] =   new Point3d(-offsetX2, innerR*Math.cos(2*Math.PI/edges*i), innerR*Math.sin(2*Math.PI/edges*i));
	    coneCoords[2*(edges+2)+i+1] =	    new Point3d(offsetX1, outerR*Math.cos(2*Math.PI/edges*i), outerR*Math.sin(2*Math.PI/edges*i));
	    coneCoords[3*(edges+2)+(edges+1)-i] =   new Point3d(offsetX2, innerR*Math.cos(2*Math.PI/edges*i), innerR*Math.sin(2*Math.PI/edges*i));
	}
	for(int i = 0; i < edges; i++)
	{
	    rectCoords[0*(edges*4)+i*4] =   new Point3d(-offsetX1, outerR*Math.cos(2*Math.PI/edges*(i+1)), outerR*Math.sin(2*Math.PI/edges*(i+1)));
	    rectCoords[0*(edges*4)+i*4+1] = new Point3d(-offsetX1, outerR*Math.cos(2*Math.PI/edges*i), outerR*Math.sin(2*Math.PI/edges*i));
	    rectCoords[0*(edges*4)+i*4+2] = new Point3d(-offsetX2, innerR*Math.cos(2*Math.PI/edges*i), innerR*Math.sin(2*Math.PI/edges*i));
	    rectCoords[0*(edges*4)+i*4+3] = new Point3d(-offsetX2, innerR*Math.cos(2*Math.PI/edges*(i+1)), innerR*Math.sin(2*Math.PI/edges*(i+1)));

	    rectCoords[1*(edges*4)+i*4] =   new Point3d(offsetX1, outerR*Math.cos(2*Math.PI/edges*(i+1)), outerR*Math.sin(2*Math.PI/edges*(i+1)));
	    rectCoords[1*(edges*4)+i*4+1] = new Point3d(offsetX1, outerR*Math.cos(2*Math.PI/edges*i), outerR*Math.sin(2*Math.PI/edges*i));
	    rectCoords[1*(edges*4)+i*4+2] = new Point3d(offsetX2, innerR*Math.cos(2*Math.PI/edges*i), innerR*Math.sin(2*Math.PI/edges*i));
	    rectCoords[1*(edges*4)+i*4+3] = new Point3d(offsetX2, innerR*Math.cos(2*Math.PI/edges*(i+1)), innerR*Math.sin(2*Math.PI/edges*(i+1)));

	}
	TriangleFanArray tfa = new TriangleFanArray(coneVertices,TriangleFanArray.COORDINATES,stripCounts);
	QuadArray qa = new QuadArray(rectVertices, QuadArray.COORDINATES, 0, stripQuadCounts);
	tfa.setCoordinates(0, coneCoords);
	qa.setCoordinates(0, rectCoords);

        translate = new Transform3D();
        transG = new TransformGroup();
        transG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
	Shape3D cone = new Shape3D(tfa);
	Shape3D rect = new Shape3D(qa);
	Appearance appCone = new Appearance();
	//appCone.setColoringAttributes(new ColoringAttributes(0.6f,0.5f,0.4f,ColoringAttributes.NICEST));
	Material matCone = new Material();
        matCone.setEmissiveColor(new Color3f(0.3f,0.5f,0.6f));
	appCone.setMaterial(matCone);
	cone.setAppearance(appCone);
	//rect.setAppearance(appCone);
*/
	//幾何部分
	Appearance appBall = new Appearance();
	Material matBall = new Material();
        matBall.setEmissiveColor(new Color3f(0.6f,0.85f,0.95f));
	appBall.setMaterial(matBall);
	Sphere ball = new Sphere(ballSize,appBall);

	Appearance appCone = new Appearance();
	Material matCone = new Material();
        matCone.setEmissiveColor(new Color3f(0.6f,0.6f,0.6f));
	appCone.setMaterial(matCone);
	Cone cone1 = new Cone(outerR,height,appCone);
	Transform3D transCone1 = new Transform3D();
	Transform3D transConeTemp = new Transform3D();
	transCone1.set(new Vector3f(-offsetX,0,0));
	transConeTemp.rotZ(Math.PI/2);
	transCone1.mul(transConeTemp);
	TransformGroup transGC1 = new TransformGroup(transCone1);
	transGC1.addChild(cone1);
	Cone cone2 = new Cone(outerR,height,appCone);
	Transform3D transCone2 = new Transform3D();
	transCone2.set(new Vector3f(offsetX,0,0));
	transConeTemp.rotZ(-Math.PI/2);
	transCone2.mul(transConeTemp);
	TransformGroup transGC2 = new TransformGroup(transCone2);
	transGC2.addChild(cone2);

        transG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        transG.addChild(transGC1);
        transG.addChild(transGC2);
	transG.addChild(ball);
        moveTo(x,y,z);
    }
    public void randomize()
    {
        double radA, radB;
        double x,y,z,r;
        double vx,vy,vz;

        radA=(Math.random()*Math.PI*2); //A 角度  [0,2PI)
        //radB=(Math.random()*Math.PI);    //B  角度 [0,PI)
        radB=Math.PI/2;                       //只有2D

        //起始位置
        x=Config.radius*Math.cos(radA)*Math.sin(radB);
        y=Config.radius*Math.sin(radA)*Math.sin(radB);
        //z=Config.radius*Math.cos(radB);
        z=0;

        //  單位向量
        vx=0-x+(Math.random()-0.5)*Config.offsetFactor/2;
        vy=0-y+(Math.random()-0.5)*Config.offsetFactor/2;
        vz=0;
        r = Math.sqrt(vx*vx+vy*vy+vz*vz);
        vx = vx/r * Config.forwardStep;
        vy = vy/r * Config.forwardStep;
        vz = vz/r * Config.forwardStep;
        
	setV(vx, vy, vz);
        moveTo(x, y, z);
    }
    public void setV(double vx, double vy, double vz)
    {
        this.vx = vx;
        this.vy = vy;
        this.vz = vz;
    }
    public void forward()
    {
        double distance = Math.sqrt(x*x+y*y+z*z);
        double minSpeedDistance = Config.boundingH/3;
        double minSpeed = Config.forwardStep/3;
        if(distance < minSpeedDistance)
        {
            double vectorLength = Math.sqrt(vx*vx+vy*vy+vz*vz);
            vx = vx/vectorLength*minSpeed;
            vy = vy/vectorLength*minSpeed;
            vz = vz/vectorLength*minSpeed;
        }
        else
        {
            double vectorLength = Math.sqrt(vx*vx+vy*vy+vz*vz);
            vx = vx/vectorLength*(Config.forwardStep*(distance-minSpeedDistance)/Config.radius+minSpeed);
            vy = vy/vectorLength*(Config.forwardStep*(distance-minSpeedDistance)/Config.radius+minSpeed);
            vz = vz/vectorLength*(Config.forwardStep*(distance-minSpeedDistance)/Config.radius+minSpeed);
        }
        move(vx,vy,vz);
	//move(0,-Config.initSpeed,0); //預設是只移向Y方向!!!
    }
}
class Capsules
{
    public LinkedList<Capsule> inScreen;
    public LinkedList<Capsule> outScreen;
    public LinkedList<Capsule> toBeOut;
    Capsules()
    {
        inScreen = new LinkedList<Capsule>();
        outScreen = new LinkedList<Capsule>();
	toBeOut = new LinkedList<Capsule>();
    }
    public void putin(Capsule c)
    {
        outScreen.remove(c);
        if(!inScreen.contains(c))
        {
            inScreen.add(c);
            c.randomize();
        }
    }
    public void putout(Capsule c)
    {
        inScreen.remove(c);
        if(!outScreen.contains(c))
        {
            outScreen.add(c);
            c.moveTo(Config.radius,Config.radius,Config.radius);    //丟到畫面外
        }
    }
    public void generateCapsules(BranchGroup TG)
    {
        for(int i=0;i<Config.maxCapsules;i++)
        {
            Capsule c = new Capsule(0,0,0,null);
            TG.addChild(c.getTransformGroup());

            if(i < Config.initCapsules)
                putin(c);
            else
                putout(c);
        }
    }
    public void proceed(int totalTime)
    {
	if(totalTime % Config.emergeTime == 0)
	{
            int num = outScreen.size();
	    if(Math.random() < Config.emergeRate && num > 0)	//抽中，隨機加入Capsule
	    {
		Capsule c = outScreen.get((int)(Math.random()*num));
		putin(c);
	    }
	}

        Iterator it = inScreen.iterator();
        while(it.hasNext())
        {
            Capsule c = (Capsule)it.next();
            if(Math.sqrt(c.x*c.x + c.y*c.y + c.z*c.z) > Config.radius)
		if(Math.random() > Config.disappearRate)    //抽中，加入消失名單
		{
		    toBeOut.add(c);
		}
		else	//沒抽中，繼續
		    c.randomize();
            else
                c.forward();
        }

	if(toBeOut.size() != 0)	//執行消失名單
	{
	    Iterator out = toBeOut.iterator();
	    while(out.hasNext())
	    {
		Capsule c = (Capsule)out.next();
		putout(c);
	    }
	    toBeOut.clear();
	}
    }
}